// 数组响应式

// 1.替换数组原型中7个方法
const orginalProto = Array.prototype;
// 备份一份，修改备份
const arrayProto = Object.create(orginalProto);
['push', 'pop', 'shift', 'unshift'].forEach(method => {
  arrayProto[method] = function () {
    // 原始操作
    orginalProto[method].apply(this, arguments)
    // 覆盖 通知更新
    console.log('数组指定' + method + '操作:' + arguments)
  }
})

// Vue.util.defineProperty(this, 'current','/')
function defineReactive(obj, key, val) {
  // 递归
  observe(val)

  // 属性拦截
  Object.defineProperty(obj, key, {
    get() {
      console.log('get', key)
      return val
    },
    set(v) {
      if (v !== val) {
        console.log('set', key)
        // 传入新值v可能还是对象
        observe(v)
        val = v
        // 通知视图更新
        // update()
      }
    },
  })
}
// 遍历传入obj的所有属性，执行响应式处理
function observe(obj) {
  // 首先判断obj是对象
  if (typeof obj !== 'object' || obj == null) {
    return obj
  }
  

  // 判断传入obj类型
  if (Array.isArray(obj)) {
    // 覆盖原型，替换7个变更操作
    obj.__proto__ = arrayProto
    // 对数组内部元素执行响应变化
    const key = Object.keys(obj)
    for (let i = 0; i < obj.length; i++) {
      observe(obj[i])
    }
  }
  Object.keys(obj).forEach(key => {
    defineReactive(obj, key, obj[key])
  })

}

// 动态新增一个属性
function set(obj, key, value) {
  defineReactive(obj, key, value)
}
const obj = {
  foo: 'foo',
  bar: 'bar',
  baz: {
    a: 1
  },
  arr:[]
}

// 用户不能手动设置，需要递归响应式处理过程
// defineReactive(obj, 'foo', 'foo')
observe(obj)


obj.foo
obj.foo = 'fsoo'
obj.bar
obj.bar = 'bar'
obj.baz
obj.baz.a 
obj.baz.a = 2
set(obj, 'bood', 'bood_val')
obj.bood
obj.bood = 1

obj.arr.push(1)
// 2.数组：支持不了
// 解决方案： 拦截数组的7个变更方法，覆盖他们，让他们做数组操作的同时，进行变更通知
